import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler, MinMaxScaler
from scripts.data_frame_generator import generate_external_time_series,generate_global_time_series, generate_blockchain_by_actor, min_max_norm,std_scale
from scripts.best_correlation import compute_best_correlation,compute_best_correlation_by_col,display_correlation_by_col
from scripts.best_correlation import get_corr_mat
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import seaborn as sns
from scipy.stats import gaussian_kde
# Récupération des séries temporelles extérieures.
external_df = generate_external_time_series("timeseries/external.csv")
# Récupération des données des 100 plus grands acteurs de la blockchain.
block_chain_by_actor_df = generate_blockchain_by_actor('timeseries/blockchain_by_actor.csv')
# Récupération des données globales.
global_df = generate_global_time_series('timeseries/global.csv')
# Normalisation de la data frame
std_scaler = StandardScaler()
df1_normalized = std_scaler.fit_transform(external_df)
df1_normalized = pd.DataFrame(np.array(df1_normalized, dtype=np.float64), columns=external_df.columns,index=external_df.index)
# Lissage de la série temporelle
df_rolling = df1_normalized.rolling(window=7).mean()
# Création de la figure Plotly Express
fig = px.line(df_rolling,x=df_rolling.index, y=["HashRate", "PriceUSD"],
title="Evolution du HashRate et du prix du Bitcoin",
labels={"value": "Valeur normalisée", "variable": "Variables", "Date": df_rolling.index.name},
template="simple_white")
# Affichage de la figure
fig.show()
En regardant les précédentes courbes affichées on peut remarquer que le HashRate et le prix en dollars augmentent de mannière comparable. Mesurons maintenant leur niveau de corrélation par la corrélation de Pearson.
correlation_matrix = external_df.corr()
correlation_matrix
| PriceUSD | HashRate | |
|---|---|---|
| PriceUSD | 1.000000 | 0.937447 |
| HashRate | 0.937447 | 1.000000 |
On peut remarquer ici que le score de correlation de Pearson entre le PriceUSD et le HashRate est de 0.93, ce qui signifie que les PriceUSD et Hashrate on une relation linéaire qui est proche.
On veut chercher ici à trouver des correlation sur l'évolution de chaque acteurs entre eux à savoir si deux acteurs ont une activité qui évolue de manière similaire comme il a été fait pour l'analyse du HashRate et du cours du Bitcoin.
On peut alors se poser la question si l'activité de certains groupes d'acteurs sont corrélées entre elles.
# Nom de la colonne à analyser dans le block_chain_by_actor_df
column_to_analyze = 'received'
# Appel d'une fonction déterminant le couple d'acteurs ayant le meilleur coefficient de corrélation
max_index,max_col, max_value = compute_best_correlation_by_col(block_chain_by_actor_df,column_to_analyze)
print(f"La valeur maximale est {max_value} et elle se trouve à l'index '{max_index}' dans la colonne '{max_col}'")
La valeur maximale est 0.9021413876901954 et elle se trouve à l'index 'BTCC.com' dans la colonne 'BtcTrade.com'
column_to_analyze = 'received'
max_index, max_col, max_value = compute_best_correlation_by_col(block_chain_by_actor_df, column_to_analyze)
def display_comparison(block_chain_by_actor_df,key1,key2,column_to_analyze,window):
std_scaler = StandardScaler()
# Filtrage des données pour la première identité
df1 = block_chain_by_actor_df[block_chain_by_actor_df['identity'] == key1].copy()
#df1 = df1.reset_index(drop=True)
df1[column_to_analyze] = df1[column_to_analyze].rolling(window=window).mean()
df1_normalized = std_scaler.fit_transform(df1[[column_to_analyze]])
df1_normalized = pd.DataFrame(np.array(df1_normalized, dtype=np.float64), columns=[column_to_analyze],index=df1.index)
# Filtrage des données pour la deuxième identité
df2 = block_chain_by_actor_df[block_chain_by_actor_df['identity'] == key2].copy()
#df1 = df1.reset_index(drop=True)
df2[column_to_analyze] = df1[column_to_analyze].rolling(window=window).mean()
df2_normalized = std_scaler.fit_transform(df2[[column_to_analyze]])
df2_normalized = pd.DataFrame(np.array(df2_normalized, dtype=np.float64), columns=[column_to_analyze],index=df2.index)
# Fusion des deux dataframes en un seul
df = pd.concat([df1, df2])
# Création de la figure Plotly Express
fig = px.line(df, x=df.index, y=column_to_analyze, color="identity",
title=f"Comparison of '{column_to_analyze}' between {key1} and {key2} (Normalized)",
labels={"value": f"{column_to_analyze} (rolling mean)", "index": "date"})
# Affichage de la figure
fig.show()
display_comparison(block_chain_by_actor_df,max_col,max_index,column_to_analyze,10)
On remarque une augmentation du nombre de transactions vers avril 2016 ainsi qu'une baisse vers juillet dans les deux courbes. On notera que le nombre de transaction n'est pas du même ordre de grandeur. C'est ici un exemple de corrélation entre deux acteurs selon un critère fixé en l'occurence le volume reçu. Voyons maintenant si les acteurs suivent une tendance commune sur un critère particulier.
Afin d'avoir une vision plus globale sur les données des acteurs ainsi que les données externes on décide de convertir les données initialement en satoshi ,telles que sent, received et sum_fee.
SATOSH_PER_BTC = 1e-8
merge_df = pd.merge(block_chain_by_actor_df, external_df[['PriceUSD']], left_index=True, right_index=True)
merge_df['sentUSD'] = merge_df['sent']*SATOSH_PER_BTC*merge_df['PriceUSD']
merge_df['receivedUSD'] = merge_df['received']*SATOSH_PER_BTC*merge_df['PriceUSD']
merge_df['sum_feeUSD'] = merge_df['sum_fee']*SATOSH_PER_BTC*merge_df['PriceUSD']
block_chain_by_actor_df = merge_df
Une fois les prix en satoshi converti en dollars, on décide de créer une data frame, qui pour chaque couple d'acteur et chaque critère va mesurer leur niveau de corrélation.
from scripts.best_correlation import best_correlation_df
best_corr_df = best_correlation_df(block_chain_by_actor_df,0)
best_corr_df = best_corr_df[best_corr_df['related_col'] !='PriceUSD'].sort_values('correlation_rate',ascending=False)
best_corr_df
| actor1 | actor2 | correlation_rate | related_col | |
|---|---|---|---|---|
| 58966 | 107 | 69697250 | 0.957747 | sum_feeUSD |
| 62953 | Bitcoin.de | CoinMotion.com | 0.950021 | sum_feeUSD |
| 63028 | Bitstamp.net | CoinSpot.com.au | 0.946132 | sum_feeUSD |
| 63237 | CoinMotion.com | Paymium.com | 0.941566 | sum_feeUSD |
| 58998 | 107 | CoinGaming.io | 0.940180 | sum_feeUSD |
| ... | ... | ... | ... | ... |
| 9727 | Loanbase.com | YoBit.net | -0.808506 | nb_received |
| 34041 | 0 | BTCJam.com | -0.812380 | nb_spent |
| 19879 | 0 | Loanbase.com | -0.833558 | nb_transactions |
| 7602 | 61 | Loanbase.com | -0.842981 | nb_received |
| 5029 | 0 | Loanbase.com | -0.849833 | nb_received |
58737 rows × 4 columns
actor1 actor2 : couples d'acteurscorrelation_rate : niveau de corrélation entre les deux acteursrelated_col : critère de corrélationOn remarque ici que 92 couples d'acteurs on un indice de corrélation elevé pour leur frais payés en dollars.
related_cols = best_corr_df.related_col.unique()
rows,cols = (len(related_cols)+1)//2,2
counter = 0
fig = make_subplots(rows=rows, cols=cols)
height_per_row,width_per_col = 400,800
for cur_col in related_cols:
cur_data = best_corr_df[best_corr_df['related_col'] == cur_col]['correlation_rate']
row,col = (counter)//2 +1,counter%2+1
fig.add_trace(
go.Histogram(x=cur_data, histnorm='probability density', name=f'{cur_col} histogramm'),
row=row, col=col
)
fig.add_trace(
go.Scatter(x=cur_data, y=gaussian_kde(cur_data)(cur_data), mode='lines',name=''),
row=row, col=col
)
counter+=1
fig.update_layout(height=height_per_row*rows, width=width_per_col*cols, title_text="Histogrammes")
# Afficher le graphique
fig.show()
""" best_corr_df = block_chain_by_actor_df.groupby(by='identity').sum()
def plot_rep(pivot_df: pd.DataFrame, colonne:str):
fig = px.pie(pivot_df,values=colonne,names=pivot_df.index)
fig.update_traces(textposition='inside')
fig.update_layout(title_text=f'{colonne} repartition.')
fig.show()
#plot_rep(pivot_df, 'received')
cols = 2
rows = 1
fig = make_subplots(rows=rows, cols=cols)
# Ajouter le diagramme camembert pour la colonne 'sum_fee'
fig.add_pie(go.Pie(labels=best_corr_df.index, values=best_corr_df['sum_fee'], name= 'Frais'), row=1, col=1)
# Ajouter le diagramme camembert pour la colonne 'spent'
fig.add_pie(go.Pie(labels=best_corr_df.index, values=best_corr_df['spent'], name='Dépenses'), row=1, col=2)
# Mettre à jour les options de layout
fig.update_traces(textposition='inside')
fig.update_layout(title_text='Repartition des frais et dépenses par date')
fig.show() """
" best_corr_df = block_chain_by_actor_df.groupby(by='identity').sum()\n\ndef plot_rep(pivot_df: pd.DataFrame, colonne:str):\n fig = px.pie(pivot_df,values=colonne,names=pivot_df.index)\n fig.update_traces(textposition='inside')\n fig.update_layout(title_text=f'{colonne} repartition.')\n fig.show()\n\n#plot_rep(pivot_df, 'received')\ncols = 2\nrows = 1\nfig = make_subplots(rows=rows, cols=cols)\n\n# Ajouter le diagramme camembert pour la colonne 'sum_fee'\nfig.add_pie(go.Pie(labels=best_corr_df.index, values=best_corr_df['sum_fee'], name= 'Frais'), row=1, col=1)\n\n# Ajouter le diagramme camembert pour la colonne 'spent'\nfig.add_pie(go.Pie(labels=best_corr_df.index, values=best_corr_df['spent'], name='Dépenses'), row=1, col=2)\n\n# Mettre à jour les options de layout\nfig.update_traces(textposition='inside')\nfig.update_layout(title_text='Repartition des frais et dépenses par date')\nfig.show() "
grouped_df = block_chain_by_actor_df.groupby('identity')[['received']].mean()
grouped_df = grouped_df.sort_values('received',ascending=False)
fig = px.bar(grouped_df.head(10), y=['received'], barmode='group')
# Afficher le graphique
fig.show()
display_correlation_by_col(merge_df.drop("PriceUSD",axis=1),window_size=7,column_to_analyze='received')
merge_df['balanceUSD'] = merge_df['receivedUSD'] - merge_df['sentUSD']
merge_df['balance'] = merge_df['received'] - merge_df['sent']